home *** CD-ROM | disk | FTP | other *** search
- Subject: v25i019: Ease 3.5 - high-level sendmail.cf language, Part03/06
- Newsgroups: comp.sources.unix
- Approved: vixie@pa.dec.com
-
- Submitted-by: Bruce G. Barnett <barnett@crdgw1.ge.com>
- Posting-number: Volume 25, Issue 19
- Archive-name: ease3.5/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 6)."
- # Contents: INTRO src/emitcf.c src/lexan.l src/main.c src/strops.c
- # Wrapped by vixie@cognition.pa.dec.com on Tue Dec 10 08:45:56 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'INTRO' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'INTRO'\"
- else
- echo shar: Extracting \"'INTRO'\" \(7853 characters\)
- sed "s/^X//" >'INTRO' <<'END_OF_FILE'
- X An introduction to Sendmail Rules
- X Copyright 1991, All rights reserved
- X Bruce Barnett
- X
- X First of all, sendmail is easy to learn, once you learned all
- about electronic mail. Figuring out how to handle the address
- X
- X bigvax::a!b!another.domain!c%d%domain.com@another.domain
- X
- is much more challenging. Here's the scoop.
- X
- X When sendmail gets an address, it always passes it to rule 3.
- X
- X Rule 3 with transform the address, and eventually sent it to
- X rule 0.
- X
- X Rule 0 makes the final decision, and selects three things:
- X
- X The address
- X The Machine to send the address to
- X The mailer to use.
- X This could be UUCP, ethernet, DECNet,
- X a local user, a program, etc.
- X
- X Once the above has been decided on, the address is transformed
- X in the following way:
- X
- X Ruleset 1 is applied to the From: line
- X Ruleset 2 is applied to the To: and Cc: line
- X
- X Each mailer then applies a rule. These rules are other unique
- X for each mailer.
- X
- X Finally ruleset 4 is applied.
- X
- X
- Now let's go through an example in detail.
- X
- grymoire% /usr/lib/sendmail -bt -C/etc/sendmail.cf
- ADDRESS TEST MODE
- XEnter <ruleset> <address>
- X> 0 user@crdgw1.crd # <---- I typed this line here
- rewrite: ruleset 3 input: "user" "@" "crdgw1" "." "crd"
- rewrite: ruleset 6 input: "user" "<" "@" "crdgw1" "." "crd" ">"
- rewrite: ruleset 6 returns: "user" "<" "@" "crdgw1" "." "LOCAL" ">"
- rewrite: ruleset 3 returns: "user" "<" "@" "crdgw1" "." "LOCAL" ">"
- rewrite: ruleset 0 input: "user" "<" "@" "crdgw1" "." "LOCAL" ">"
- rewrite: ruleset 0 returns: $# "ether" $@ "crdgw1" $: "user" "<" "@" "crdgw1" ">"
- X>
- X
- Rule 3 can be given any address at all. It must determine the machine
- and domain which corresponds to the address. Determining the machine
- can be tricky, because it depends o the address. What it uses to
- specify the address is to surround the hostname and @ sign with angle brackets.
- It also added a imaginary domain to the hostname to indicate the type
- of network it is on. The set of angle brackets is used to "focus" on a machine.
- X
- Some typical values are:
- X
- X < @ machine . LOCAL > => a local host
- X < @ machine > => same as above
- X < @ machine . UUCP > => a machine on the UUCP network
- X
- The angle brackets indicate the important part - the machine and
- perhaps what mail agent to use. However, the username isn't included
- in the set of charatcers surrounded by angle brackets. The problem is,
- different mailers have the username in a different format. In some
- casess, the host is the first word, in others it's the last word.
- X
- Here is an example of an address going into rule 3 and the expected
- output:
- X
- X Input Output
- X a!b!c!d!user <@a.UUCP>!b!c!d!user or
- X b!c!d!user<@a.UUCP>
- X user@a.uucp user<@a.uucp>
- X bigvax::user user<@bigvax.DECNET>
- X user%a.com@b.edu user%a.com<@b.edu> or - it you are agressive
- X user<@a.com>
- X a!b!user@abc.edu a!b!user<@abc.edu>
- X @a:user@b.com <@a>:user@b.com
- X "Bruce" <barnett@local> barnett<@local>
- X
- As you can see, the machine that will accept the message will be
- different depending on the address. Ruleset 3 must find the right
- machine, and also clean up any addresses if appropriate.
- It does it's work by looking for a pattern, and transforming the
- address when it matches the pattern.
- X
- The cleaning up part can be confusing, but typically ruleset 3 calls
- other rules to do this. One rule is used to clean up addresses before
- the < and > are added. Another rule is used to clean up addresses
- after it has been converted into the < @ machine > format.
- X
- Here is the ease version of the rule that transforms a UUCP address:
- X
- X if ( exactly_one ! one_or_more ) /* uucphost!user */
- X return (RULESET_6 ($2<@$1."uucp">));
- X
- This transforms the address, but calls ruleset 6, which cleans up the
- addresses with < and >. The variables "exactly_one" and "one_or_more"
- match that number of tokens, and are replaced by the $1 or $2 on the
- returned rule. ($1 is exactly_one, $2 is one_or_more).
- X
- Here is a rule in ruleset 6 that looks for an address to the local
- domain, and replaces the domain with "LOCAL":
- X
- X if ( zero_or_more <@ zero_or_more any_in_mydomainname > zero_or_more ) /* convert local domain */
- X retry ($1<@$2"LOCAL">$4);
- X
- zero_or_more is a pattern, which matches $1, $2, or $4.
- any_in_mydomain is a special pattern that matches the domain. It is
- not necessary to have a $3 because the domain is known.
- So the test of the address user@crdgw1.crd reports this:
- X
- rewrite: ruleset 3 input: "user" "@" "crdgw1" "." "crd"
- rewrite: ruleset 6 input: "user" "<" "@" "crdgw1" "." "crd" ">"
- rewrite: ruleset 6 returns: "user" "<" "@" "crdgw1" "." "LOCAL" ">"
- rewrite: ruleset 3 returns: "user" "<" "@" "crdgw1" "." "LOCAL" ">"
- X
- Once ruleset 3 is down, it passes the address to 0.
- This eventually gets to the rule:
- X
- X/* deliver to known ethernet hosts explicitly specified in our domain */
- X if ( zero_or_more <@ any_in_etc_hosts."LOCAL"> zero_or_more ) /* user@host.sun.com */
- X resolve (mailer (ether),
- X host ($2 ),
- X user ($1<@$2>$3));
- X
- This matches, so the ether mailer is used, and the address is
- X$1<@2>$3, or in this case:
- X
- X
- rewrite: ruleset 0 returns: $# "ether" $@ "crdgw1" $: "user" "<" "@" "crdgw1" ">"
- X
- The $#, $@, and $: are sendmail talk for the mailer, machine, and
- address.
- X
- Still more to come. The specificalion of the mailer is:
- X
- mailer
- X ether {
- X Path = "[TCP]",
- X Flags = { f_mult, f_strip, f_date, f_from, f_mesg, f_upperu, f_addrw, f_dot },
- X Sender = RULESET_11,
- X Recipient = RULESET_21,
- X Argv = "TCP ${m_rhost}"
- X };
- X
- X
- This says the sender's address must go thru rule 11, which means rules
- X1, 11, and 4. The recipient's address goes through 2, 21, and 4.
- X
- To test this, type the address from ruleset 0 and specify either 1,
- X11, and 4 or perhaps 2, 21, and 4:
- X
- X> 1,11,4 user@crdgw1
- rewrite: ruleset 3 input: "user" "@" "crdgw1"
- rewrite: ruleset 6 input: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 6 returns: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 3 returns: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 1 input: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 1 returns: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 11 input: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 11 returns: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 4 input: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 9 input: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 9 returns: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 4 returns: "user" "@" "crdgw1"
- X
- As you can see, ruleset 3 is always applied first, which calls 6,
- Then rule 1 is applied, followed by rule 11, and then followed by
- rule 4. The end result tells me the From: line would look like
- user@crdgw1
- X
- X
- The uucp mailer has a diffent set of rewrite rules.
- In sun's sendmail.main.cf, it uses 13 and 23. To test this address,
- I typed 1,13,4 and got this:
- X
- X> 1,13,4 user@crdgw1
- rewrite: ruleset 3 input: "user" "@" "crdgw1"
- rewrite: ruleset 6 input: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 6 returns: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 3 returns: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 1 input: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 1 returns: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 13 input: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 5 input: "user" "<" "@" "crdgw1" ">"
- rewrite: ruleset 5 returns: "crdgw1" "!" "user"
- rewrite: ruleset 13 returns: "grymoire" "!" "crdgw1" "!" "user"
- rewrite: ruleset 4 input: "grymoire" "!" "crdgw1" "!" "user"
- rewrite: ruleset 9 input: "grymoire" "!" "crdgw1" "!" "user"
- rewrite: ruleset 9 returns: "grymoire" "!" "crdgw1" "!" "user"
- rewrite: ruleset 4 returns: "grymoire" "!" "crdgw1" "!" "user"
- X>
- X
- As you can see, it converted the address into a uucp path relative to
- my machine.
- X
- To test these three cases, add the following to your debug.in file:
- X
- X0 user@crdgw1
- X1,11,4 user@crdgw1 From_Ethernet_to_Ethernet
- X1,13,4 user@crdgw1 From_Ethernet_to_UUCP
- X
- END_OF_FILE
- if test 7853 -ne `wc -c <'INTRO'`; then
- echo shar: \"'INTRO'\" unpacked with wrong size!
- fi
- # end of 'INTRO'
- fi
- if test -f 'src/emitcf.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/emitcf.c'\"
- else
- echo shar: Extracting \"'src/emitcf.c'\" \(7842 characters\)
- sed "s/^X//" >'src/emitcf.c' <<'END_OF_FILE'
- X#ifdef FLUKE
- X# ifndef LINT
- X static char RCSid[] = "@(#)FLUKE $Header: /home/kreskin/u0/barnett/Src/Ease/ease/src/RCS/emitcf.c,v 3.0 1991/02/22 18:50:27 barnett Exp $";
- X# endif LINT
- X#endif FLUKE
- X
- X/*
- X * emitcf.c -- This file contains routines associated with the writing
- X * and formatting of a translated sendmail configuration file.
- X *
- X * author -- James S. Schoner, Purdue University Computing Center,
- X * West Lafayette, Indiana 47907
- X *
- X * date -- July 9, 1985
- X *
- X * Copyright (c) 1985 by Purdue Research Foundation
- X *
- X * All rights reserved.
- X *
- X * $Log: emitcf.c,v $
- X * Revision 3.0 1991/02/22 18:50:27 barnett
- X * Added support for HP/UX and IDA sendmail.
- X *
- X * Revision 2.1 1990/01/30 14:09:49 jeff
- X * Changes by Bruce Barnett - extensions for SunOS/Ultrix.
- X *
- X * Revision 2.0 88/06/15 14:40:47 root
- X * Baseline release for net posting. ADR.
- X */
- X
- X#include <stdio.h>
- X#include "symtab.h"
- X#include "fixstrings.h"
- X
- X#define REGLINE 60 /* length of output lines which may be continued */
- X#define MAXLINE 256 /* liberal maximum line length */
- X
- extern short Rformat; /* read-format flag for a class */
- extern char *MacScan ();
- extern char MakeMac ();
- extern void PrintError (),
- X FatalError (),
- X PrintWarning (),
- X ErrorReport ();
- X
- void PrintDef ();
- X
- static char ClassCH; /* printable class macro char */
- X
- X/*
- X * EmitDef () -- Emit a definition line (Ease block definition) in cf
- X * format.
- X *
- X */
- void
- XEmitDef (blockdef, targ, defstr1, defstr2)
- register enum bdefs blockdef; /* type of definition */
- register struct he *targ; /* target to be defined */
- char *defstr1, *defstr2; /* one or two definition strings */
- X{
- X /*
- X * This routine is about as pretty as a translated ease file...
- X * Each type of line (Ease block) is handled case by case below.
- X *
- X */
- X switch (blockdef) {
- X case def_macro: printf ("D%c", MakeMac (targ, ID_MACRO));
- X PrintDef (def_macro, MacScan (defstr1));
- X if (ISMACRO(targ->idd))
- X PrintWarning ("Redefining macro %s.\n", targ->psb);
- X targ->idd |= ID_MACRO; /* signal definition */
- X break;
- X
- X case def_class: if (Rformat) /* read format */
- X printf ("F");
- X else
- X printf ("C");
- X printf ("%c", ClassCH = MakeMac (targ, ID_CLASS));
- X if (Rformat) { /* read format */
- X printf ("%s\n", defstr1);
- X Rformat = FALSE;
- X } else
- X PrintDef (def_class, MacScan(defstr1));
- X if (ISCLASS(targ->idd))
- X PrintWarning ("Appending to previously defined class %s.\n", targ->psb);
- X targ->idd |= ID_CLASS; /* signal definition */
- X break;
- X
- X case def_option: if (defstr1 == NULL)
- X FatalError ("No option passed in EmitDef()", (char *)NULL);
- X printf ("O%c", *defstr1);
- X PrintDef (def_option, defstr2);
- X break;
- X
- X case def_prec: printf ("P%s=%d\n", targ->psb, targ->idval.prec);
- X break;
- X
- X case def_trusted: printf ("T");
- X PrintDef (def_trusted, defstr1);
- X break;
- X
- X case def_header: printf ("H");
- X if (defstr1 != NULL)
- X printf ("?%s?", defstr1);
- X PrintDef (def_header, defstr2);
- X break;
- X
- X case def_mailer: if (ISMAILER(targ->idtype)) {
- X if (ISMAILER(targ->idd))
- X PrintWarning ("Redefining mailer %s.\n", targ->psb);
- X } else if (ISTYPED(targ->idtype)) {
- X PrintError ("Redeclaration of identifier as mailer: %s", targ->psb);
- X return;
- X }
- X targ->idd |= ID_MAILER; /* signal definition */
- X printf ("M%s, ", targ->psb);
- X PrintDef (def_mailer, defstr1);
- X break;
- X
- X case def_ruleset: printf ("R");
- X PrintDef (def_ruleset, defstr1);
- X break;
- X
- X default: FatalError ("Bad case in EmitDef ()", (char *) NULL);
- X }
- X}
- X
- X
- X/*
- X * PrintContinued () -- Print a line definition (buf) by splitting it over
- X * more than one line. The two definition types
- X * accepted for this method of continuation are class
- X * and trusted user lists, indicated in the argument
- X * btype
- X *
- X */
- void
- PrintContinued (btype, buf)
- enum bdefs btype; /* block (line) type for definition */
- register char *buf; /* buffer containing the definition */
- X{
- X register char *tmp; /* breakpoint search pointer */
- X register char tc; /* temporary swap byte */
- X int buflen; /* length of definition buffer */
- X
- X buflen = strlen (buf);
- X tmp = buf + REGLINE;
- X while ((*--tmp != ' ') && (tmp != buf)) /* look for suitable break */
- X /* null */ ;
- X if (tmp == buf) {
- X for (tmp = buf + REGLINE; (*tmp != ' ') && (tmp - buf != buflen); tmp++)
- X /* null */ ;
- X if ((tmp - buf) >= MAXLINE)
- X PrintWarning ("Member name may be too long.\n", (char *) NULL);
- X }
- X tc = *tmp; /* swap break char with null char */
- X *tmp = '\0';
- X printf ("%s\n", buf);
- X if ((*tmp = tc) == '\0')
- X return;
- X else
- X tmp++;
- X if (btype == def_class) /* start next line */
- X printf ("C%c", ClassCH);
- X else
- X printf ("T");
- X if (strlen (tmp) < REGLINE) /* continue the line */
- X printf ("%s\n", tmp);
- X else
- X PrintContinued (btype, tmp);
- X}
- X
- X
- X/*
- X * PrintDef () -- Handles special cases (like line continuation) when
- X * printing definitions.
- X *
- X */
- void
- PrintDef (btype, dstr)
- register enum bdefs btype; /* block type (output line type) */
- register char *dstr; /* definition string */
- X{
- X register char *tmp;
- X
- X if (dstr == (char *)NULL)
- X dstr = "";
- X
- X for (tmp = dstr; *tmp != '\0'; tmp++) /* search for line continuations */
- X if ((*tmp == '\\') && (*++tmp == '\n'))
- X if (btype != def_header) {
- X ErrorReport ("Non-header string contains line continuation\n");
- X return;
- X } else
- X break;
- X
- X /*
- X * Perform case by case handling of definition printing.
- X *
- X */
- X switch (btype) {
- X case def_header : if (*tmp-- == '\n') {
- X *tmp = '\0';
- X if (tmp - dstr >= MAXLINE)
- X PrintWarning ("Header may be too long.\n",
- X (char *) NULL);
- X printf ("%s\n\t", dstr);
- X tmp += 2;
- X PrintDef (def_header, tmp);
- X } else {
- X if (strlen (dstr) >= MAXLINE)
- X PrintWarning ("Header may be too long.\n",
- X (char *) NULL);
- X printf ("%s\n", dstr);
- X }
- X break;
- X
- X case def_mailer : if (strlen (dstr) >= MAXLINE)
- X PrintWarning ("Mailer definition may be too long.\n",
- X (char *) NULL);
- X printf ("%s\n", dstr);
- X break;
- X
- X case def_ruleset: if (strlen (dstr) >= MAXLINE)
- X PrintWarning ("Rewriting rule may be too long.\n",
- X (char *) NULL);
- X printf ("%s\n", dstr);
- X break;
- X
- X case def_option : if (strlen (dstr) >= MAXLINE)
- X PrintWarning ("Option assignment may be too long.\n",
- X (char *) NULL);
- X printf ("%s\n", dstr);
- X break;
- X
- X case def_macro : if (strlen (dstr) >= MAXLINE)
- X PrintWarning ("Macro assignment may be too long.\n",
- X (char *) NULL);
- X printf ("%s\n", dstr);
- X break;
- X
- X case def_prec : if (strlen (dstr) >= MAXLINE)
- X PrintWarning ("Precedence relation may be too long.\n",
- X (char *) NULL);
- X printf ("%s\n", dstr);
- X break;
- X
- X case def_trusted:
- X case def_class : if (strlen (dstr) < REGLINE)
- X printf ("%s\n", dstr);
- X else /* use line continuation feature */
- X PrintContinued (btype, dstr);
- X break;
- X
- X default : FatalError ("Invalid case in PrintDef ()", (char *) NULL);
- X }
- X}
- X
- X
- X/*
- X * StartRuleset () -- Prints a ruleset heading for the ruleset identifier
- X * contained in the argument rsid.
- X *
- X */
- void
- StartRuleset (rsid)
- register struct he *rsid; /* ruleset identifier */
- X{
- X if (!ISRULESET(rsid->idtype))
- X if (ISTYPED(rsid->idtype))
- X PrintError ("Identifier not of ruleset type: %s", rsid->psb);
- X else
- X PrintError ("Ruleset identifier not bound to a number: %s", rsid->psb);
- X else {
- X if (ISRULESET(rsid->idd))
- X PrintWarning ("Redefining ruleset %s.\n", rsid->psb);
- X rsid->idd |= ID_RULESET;
- X printf ("S%s\n", rsid->idval.rsn);
- X }
- X}
- END_OF_FILE
- if test 7842 -ne `wc -c <'src/emitcf.c'`; then
- echo shar: \"'src/emitcf.c'\" unpacked with wrong size!
- fi
- # end of 'src/emitcf.c'
- fi
- if test -f 'src/lexan.l' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/lexan.l'\"
- else
- echo shar: Extracting \"'src/lexan.l'\" \(8822 characters\)
- sed "s/^X//" >'src/lexan.l' <<'END_OF_FILE'
- X%{
- X
- X#ifdef FLUKE
- X# ifndef LINT
- X static char RCSid[] = "@(#)FLUKE $Header: /home/kreskin/u0/barnett/Src/ease/src/RCS/lexan.l,v 3.2 1991/05/16 10:45:25 barnett Exp $";
- X# endif LINT
- X#endif FLUKE
- X
- X/*
- X * lexan.l -- Lexical Analyzer for EASE.
- X *
- X * Contains code for lex(1) which generates a lexical
- X * analyzer (lex.yy.c) for Ease, a high-level specification
- X * format for sendmail configuration files.
- X *
- X * author -- James S. Schoner, Purdue University Computing Center,
- X * West Lafayette, Indiana 47907
- X *
- X * date -- July 1, 1985
- X *
- X * Copyright (c) 1985 by Purdue Research Foundation
- X *
- X * All rights reserved.
- X *
- X * $Log: lexan.l,v $
- X * Revision 3.2 1991/05/16 10:45:25 barnett
- X * Better support for System V machines
- X * Support for machines with read only text segments
- X *
- X * Revision 3.1 1991/02/25 22:09:52 barnett
- X * Fixed some portability problems
- X *
- X * Revision 3.0 1991/02/22 18:50:27 barnett
- X * Added support for HP/UX and IDA sendmail.
- X *
- X * Revision 2.3 1991/02/12 20:49:34 barnett
- X * Added several new tokens.
- X * Merged Jeff's changes with my own.
- X *
- X * Revision 2.2 1990/05/07 11:12:53 jeff
- X * Add support for the "Cflag" variable which controls whether or not
- X * input lines are passed through as comments in the output stream.
- X *
- X * Version 2.1 90/01/30 15:26:23 jeff
- X * If -C flag is specified, emit input as comments in the output stream.
- X *
- X * Revision 2.0 88/06/15 15:11:30 root
- X * Baseline release for net posting. ADR.
- X *
- X */
- X
- X#include "fixstrings.h"
- X#include "symtab.h"
- X#include "lexdefs.h"
- X
- X#define LEXnewline '\n'
- X#define LEXeof '\0'
- X#define MaxFN 200 /* maximum file name length */
- X
- extern int EchoInputAsComments;
- extern struct he *LookupSymbol ();
- extern void ErrorReport ();
- extern void yymark();
- extern void PrintError();
- extern char * malloc ();
- X
- int Lcount; /* line counter */
- char FNbuf[MaxFN]; /* file name buffer */
- short RMatch = FALSE; /* ruleset match flag */
- X
- X#ifdef YYDEBUG
- extern int yychar;
- X#else
- int yychar;
- X#endif
- X
- X#undef input
- X# define input() (((yytchar=yychar=yysptr>yysbuf?U(*--yysptr):Getc(yyin,yyout))==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)
- X
- int
- Getc (yyin, yyout)
- X FILE *yyin, *yyout;
- X{
- X static char linbuf[BUFSIZ], *pc = linbuf;
- X char c;
- X
- X /* initialize buffer: first call only */
- X if (*pc == '\0' && pc == linbuf) {
- X if (fgets(linbuf, BUFSIZ, yyin)==NULL)
- X return EOF;
- X /* echo input as comment */
- X if (EchoInputAsComments) {
- X fprintf(yyout, "%s%s", (linbuf[0] == '#' ? "" : "# "), linbuf);
- X }
- X }
- X c = *pc++;
- X if (c == '\n') {
- X pc = linbuf;
- X if (fgets(linbuf, BUFSIZ, yyin) == NULL)
- X *pc = (char) EOF;
- X else
- X /* echo input as comment (except cpp comments) */
- X if (EchoInputAsComments) {
- X fprintf(yyout, "%s%s",
- X (linbuf[0] == '#' ? "" : "# "), linbuf);
- X }
- X }
- X return (c == (char) EOF) ? EOF : c;
- X}
- X
- X/*
- X * Table of keywords. NOTE: This is in sorted order, and
- X * must stay that way if anything else is added to it.
- X */
- static struct resword {
- X char *r_text;
- X int r_tokval;
- X} reswords[] = {
- X { "Argv", MARGV },
- X { "Eol", MEOL },
- X { "Flags", MFLAGS },
- X { "Maxsize", MMAXSIZE },
- X { "Path", MPATH },
- X { "Recipient", MRECIPIENT },
- X { "Sender", MSENDER },
- X { "alias", ALIAS },
- X { "asm", ASM },
- X { "bind", BIND },
- X { "canon", CANON },
- X { "class", CLASS },
- X { "concat", CONCAT },
- X { "d_background", DOPTB },
- X { "d_interactive", DOPTI },
- X { "d_queue", DOPTQ },
- X { "dbm", DBM }, /* IDA */
- X { "default", DEFAULT }, /* IDA */
- X { "define", DEFINE },
- X { "eval", EVAL },
- X { "f_addrw", CCFLAG },
- X { "f_arpa", AAFLAG },
- X { "f_bsmtp", BBFLAG }, /* IDA */
- X { "f_date", DDFLAG },
- X { "f_dot", XXFLAG },
- X { "f_escape", EEFLAG },
- X { "f_expensive", EFLAG },
- X { "f_ffrom", FFLAG },
- X { "f_from", FFFLAG },
- X { "f_full", XFLAG },
- X { "f_llimit", LLFLAG },
- X { "f_locm", LFLAG },
- X { "f_mail11", HHFLAG }, /* Ultrix */
- X { "f_mesg", MMFLAG },
- X { "f_mult", MFLAG },
- X { "f_noreset", SSFLAG },
- X { "f_noufrom", NFLAG },
- X { "f_relativize", VVFLAG }, /* IDA */
- X { "f_retsmtp", PFLAG },
- X { "f_return", PPFLAG },
- X { "f_rfrom", RFLAG },
- X { "f_rport", RRFLAG },
- X { "f_smtp", IIFLAG },
- X { "f_strip", SFLAG },
- X { "f_ufrom", UUFLAG },
- X { "f_upperh", HFLAG },
- X { "f_upperu", UFLAG },
- X { "field", FIELD },
- X { "for", FOR },
- X { "h_exit", EOPTE },
- X { "h_mail", EOPTM },
- X { "h_mailz", EOPTZ },
- X { "h_print", EOPTP },
- X { "h_write", EOPTW },
- X { "header", HEADER },
- X { "host", HOST },
- X { "hostnum", HOSTNUM },
- X { "if", IF },
- X { "ifset", IFSET },
- X { "in", IN },
- X { "macro", MACRO },
- X { "mailer", MAILER },
- X { "map", MAP },
- X { "match", MATCH },
- X { "next", NEXT },
- X { "o_alias", AAOPT },
- X { "o_aliasfile", YYOPT }, /* SunOS */
- X { "o_bsub", BBOPT },
- X { "o_checkpoint", CCOPT },
- X { "o_delivery", DOPT },
- X { "o_dmuid", UOPT },
- X { "o_dnet", NNOPT },
- X { "o_envelope", SLOPT }, /* IDA */
- X { "o_ewait", AOPT },
- X { "o_flog", SSOPT },
- X { "o_fsmtp", HHOPT },
- X { "o_gid", GOPT },
- X { "o_handling", EOPT },
- X { "o_hformat", OOPT },
- X { "o_loadnc", XXOPT },
- X { "o_loadq", XOPT },
- X { "o_maxempty", BOPT }, /* SunOS */
- X { "o_maxhops", HOPT }, /* SunOS */
- X { "o_nameserver", IIOPT }, /* HP/UX */
- X { "o_newproc", YYOPT },
- X { "o_nfs", RROPT }, /* SunOS 4.0 */
- X { "o_pmaster", PPOPT },
- X { "o_prifactor", ZOPT },
- X { "o_qdir", QQOPT },
- X { "o_qfactor", QOPT },
- X { "o_qtimeout", TTOPT },
- X { "o_qwait", COPT },
- X { "o_rebuild", DDOPT },
- X { "o_recipfactor", YOPT },
- X { "o_rsend", MOPT },
- X { "o_safe", SOPT },
- X { "o_skipd", IOPT },
- X { "o_slog", LLOPT },
- X { "o_timezone", TOPT },
- X { "o_tmode", FFOPT },
- X { "o_tread", ROPT },
- X { "o_usave", FOPT },
- X { "o_validate", NOPT },
- X { "o_verbose", VOPT },
- X { "o_waitfactor", ZZOPT },
- X { "o_wizpass", WWOPT },
- X { "options", OPTIONS },
- X { "precedence", PRECEDENCE },
- X { "program", PROGRAM }, /* HP/UX */
- X { "quote", QUOTE },
- X { "readclass", READCLASS },
- X { "resolve", RESOLVE },
- X { "resolved", RESOLVED },
- X { "retry", RETRY },
- X { "return", RETURN },
- X { "ruleset", RULESET },
- X { "trusted", TRUSTED },
- X { "user", USER },
- X { "while", IF },
- X { "ypalias", YPALIAS }, /* Ultrix */
- X { "ypmap", YPMAP }, /* SunOS */
- X { "yppasswd", YPPASSWD }, /* Ultrix */
- X};
- X%}
- X
- X%%
- X int INch; /* any input character */
- X
- X[ \t\f]+ ; /* discard whitepsace */
- X[\n] Lcount++;
- X^\#[ \t]*[0-9]+[ \t]*\".*\"[ \t]*.*[\n] {
- X/* sscanf (yytext, "%*c%d%s", &Lcount, FNbuf); */
- X yymark();
- X }
- X[A-Za-z_][A-Za-z0-9_-]* {
- X register int l, h, m, r, c;
- X
- X l = 0;
- X h = (sizeof (reswords) / sizeof(reswords[0])) - 1;
- X while (l <= h) {
- X m = (h + l) / 2;
- X c = yytext[0] - reswords[m].r_text[0];
- X r = c ? c : strcmp (yytext, reswords[m].r_text);
- X if (r < 0)
- X h = m - 1;
- X else if (r > 0)
- X l = m + 1;
- X else
- X return reswords[m].r_tokval;
- X }
- X
- X /* not a keyword */
- X
- X /* store identifiers in symbol table */
- X yylval.phe = LookupSymbol (yytext);
- X return (IDENT);
- X }
- X["]((\\\n)|(\\\")|[^"\n])* {
- X if ((INch = input()) == LEXnewline) {
- X ErrorReport ("End of line in string.\n");
- X unput (INch);
- X }
- X fixquotes ();
- X yylval.psb = (char *) malloc (strlen (yytext) + 1);
- X strcpy (yylval.psb, yytext + 1);
- X return (SCONST);
- X }
- X[0][0-7]* {
- X sscanf (yytext, "%o", &yylval.ival); /* octal constant */
- X return (ICONST);
- X }
- X[-]?[1-9][0-9]* {
- X yylval.ival = atoi (yytext);
- X return (ICONST);
- X }
- X"=" return (ASGN);
- X"," return (COMMA);
- X"{" return (LBRACE);
- X"}" return (RBRACE);
- X"(" return (LPAREN);
- X")" return (RPAREN);
- X";" return (SEMI);
- X"$" return (DOLLAR);
- X":" return (COLON);
- X"*" return (STAR);
- X"/*" {
- X /* eat C comments */
- X INch = input ();
- X while ((INch != '*') ||
- X ((INch = input ()) != '/')) {
- X if (INch == LEXnewline)
- X Lcount++;
- X else
- X if (INch == LEXeof) {
- X ErrorReport ("End of file in comment.\n");
- X break;
- X }
- X if (INch != '*')
- X INch = input ();
- X }
- X }
- X"/" return (SLASH);
- X[\\]?. {
- X if (RMatch) { /* in rulesets, return literal character */
- X yylval.ival = (yytext[0] == '\\') ? yytext[1] : yytext[0];
- X return (SEPCHAR);
- X } else {
- X PrintError ("Illegal delimiter character: (octal code) \\%03o", *yytext);
- X }
- X }
- X%%
- X
- X/*
- X * fixquotes --- inside a "quoted string", turn `\"' into just `"'
- X *
- X * this is most useful inside the Argv strings for mailers,
- X * particularly when debugging.
- X */
- X
- fixquotes ()
- X{
- X register char *cp1, *cp2;
- X
- X cp1 = cp2 = yytext;
- X while (*cp2) {
- X /*
- X * if we really wanted to get fancy,
- X * at this point we'd handle C escapes,
- X * but I don't think it's necessary.
- X */
- X if (*cp2 == '\\' && cp2[1] == '"')
- X cp2++;
- X *cp1++ = *cp2++;
- X }
- X *cp1++ = *cp2++; /* final '\0' */
- X}
- END_OF_FILE
- if test 8822 -ne `wc -c <'src/lexan.l'`; then
- echo shar: \"'src/lexan.l'\" unpacked with wrong size!
- fi
- # end of 'src/lexan.l'
- fi
- if test -f 'src/main.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/main.c'\"
- else
- echo shar: Extracting \"'src/main.c'\" \(7952 characters\)
- sed "s/^X//" >'src/main.c' <<'END_OF_FILE'
- X#ifdef FLUKE
- X# ifndef LINT
- X static char RCSid[] = "@(#)FLUKE $Header: /home/kreskin/u0/barnett/Src/ease/src/RCS/main.c,v 3.2 1991/05/16 10:45:25 barnett Exp $";
- X# endif LINT
- X#endif FLUKE
- X
- X/*
- X * main.c -- Main procedure for Ease Translator.
- X *
- X * author -- James S. Schoner, Purdue University Computing Center
- X * West Lafayette, Indiana 47907
- X *
- X * date -- July 9, 1985
- X *
- X * Copyright (c) 1985 by Purdue Research Foundation
- X *
- X * All rights reserved.
- X *
- X * $Log: main.c,v $
- X * Revision 3.2 1991/05/16 10:45:25 barnett
- X * Better support for System V machines
- X * Support for machines with read only text segments
- X *
- X * Revision 3.1 1991/02/25 22:09:52 barnett
- X * Fixed some portability problems
- X *
- X * Revision 2.2 1990/05/07 11:14:02 jeff
- X * Add support for the "-q" flag which controls whether input lines
- X * are passed through as comments in the output stream.
- X *
- X * Version 2.1 90/01/30 15:37:16 jeff
- X * Filter input file through cpp before processing it.
- X *
- X * Revision 2.0 88/06/15 14:42:41 root
- X * Baseline release for net posting. ADR.
- X *
- X */
- X
- X
- X#ifndef CPP /* filename of preprocessor */
- X# define CPP "/lib/cpp"
- X#endif CPP
- X
- X#ifndef CPPARGS /* valid arguments of preprocessor */
- X#ifdef sun /* Sun's cpp has more options - I guess */
- X# define CPPARGS "BCHpPRTDIUY"
- X#else
- X# define CPPARGS "CDEIPU"
- X#endif sun
- X#endif CPP
- X
- X#include "fixstrings.h"
- X#include <stdio.h>
- X#include <ctype.h>
- X#ifdef SYSV
- X#define index strchr
- X#define rindex strrchr
- X#endif
- X#ifdef MALLOC_DEBUG
- extern int malloc_debug();
- extern int malloc_verify();
- X#endif /* MALLOC_DEBUG */
- X
- extern FILE *DIAGf; /* diagnostic file */
- char *infile = 0; /* input file name */
- char *outfile = 0; /* output file name */
- extern void InitError (),
- X#ifndef DATA_RW
- X InitStrOps (),
- X InitParser (),
- X#endif
- X InitSymbolTable (),
- X DefScan (),
- X FatalError (),
- X PreLoad ();
- X
- int EchoInputAsComments = 1; /* should input lines be echoed
- X * as comments?
- X */
- int ErrorCount; /* translation error count */
- void GetArgs (); /* gets arguments to "et" */
- X
- X#ifdef YYDEBUG
- extern int yydebug;
- X#else
- static int yydebug;
- X#endif
- X
- X/*
- X * main () -- Main procedure for the Ease Translator et. If no files are
- X * given as arguments to et, stdin is translated and written to
- X * stdout. If one file is given, it is translated and written
- X * to stdout. If two files are given, the first is translated
- X * and written to the second. If the first filename is "-",
- X * standard input is assumed. A translation is performed on
- X * valid Ease input only, producing a regular sendmail
- X * configuration file.
- X *
- X */
- void
- main (argc, argv)
- int argc; /* argument count for "et" */
- char *argv[]; /* argument vector for "et" */
- X{
- X#ifdef MALLOC_DEBUG
- X malloc_debug(1);
- X#endif MALLOC_DEBUG
- X InitError (); /* initialize error conditions */
- X#ifndef DATA_RW
- X InitParser ();
- X InitStrOps();
- X
- X#endif
- X InitSymbolTable (); /* initialize the symbol table */
- X PreLoad (); /* preload special identifiers */
- X GetArgs (argc, argv); /* set up argument files */
- X (void) yyparse (); /* perform translation */
- X if (fflush (stdout) == EOF)
- X FatalError ("Cannot flush output stream/file", (char *) NULL);
- X DefScan (); /* warn about undefined idents */
- X if (ErrorCount)
- X fprintf (DIAGf, "\n\n*** %d error(s) detected.\n", ErrorCount);
- X exit (ErrorCount);
- X}
- X
- X
- X/*
- X * GetArgs () -- Processes arguments to the Ease translator "et". The
- X * arguments are files (margv) which may replace either/both
- X * of the files standard input and standard output. The
- X * following cases are possible:
- X *
- X * -- et f.e f.cf
- X * Translate Ease file f.e and write result
- X * to f.cf.
- X *
- X * -- et f.e
- X * Translate Ease file f.e and write result to
- X * standard output.
- X *
- X * -- et - f.cf
- X * Translate standard input and write result to
- X * f.cf.
- X *
- X * -- et
- X * Translate standard input and write result to
- X * standard output.
- X *
- X * et also accepts arguments. These include the /lib/cpp arguments
- X * and the -d argument for debugging grammars.
- X *
- X * Finally, a message indicating the volatility of the
- X * Ease output is written.
- X *
- X */
- void
- GetArgs (margc, margv)
- register int margc; /* argument count */
- register char **margv; /* argument vector */
- X{
- X int cppflags = 0;
- X int otherflags = 0;
- X int arg;
- X
- X for (arg = 1; arg < margc; ++arg) { /* scan arguments */
- X if (margv[arg][0] == '-') { /* a flag?*/
- X if (isalpha(margv[arg][1])) { /* yes - a flag */
- X if (index(CPPARGS,margv[arg][1])) ++cppflags; /* one belonging to the CPP */
- X else if (margv[arg][1] == 'd' ) yydebug = 1;
- X else if (margv[arg][1] == 'q' ) EchoInputAsComments = 0;
- X else ++otherflags;
- X } else if (! margv[arg][1]) { /* this argument is just a '-' */
- X if ( (arg - yydebug - cppflags - otherflags) == 1 )
- X infile = margv[arg];
- X else if ( (arg - yydebug - cppflags - otherflags) == 2 )
- X outfile = margv[arg];
- X else
- X FatalError ("Usage: et [-%s] [infile [outfile]]", CPPARGS);
- X } else {
- X FatalError ("Usage: et [-%s] [infile [outfile]]", CPPARGS);
- X } /* end if a -argument */
- X } else { /* a filename - i guess */
- X if ( (arg - yydebug - cppflags - otherflags) == 1 )
- X infile = margv[arg];
- X else if ( (arg - yydebug - cppflags - otherflags) == 2 )
- X outfile = margv[arg];
- X else
- X FatalError ("Usage: et [-d] [-q] [-%s] [infile [outfile]]", CPPARGS);
- X } /* end if a filename argument */
- X } /* done with parsing all of the arguments */
- X if (otherflags)
- X FatalError ("Usage: et [-%s] [infile [outfile]]", CPPARGS);
- X if (infile && strcmp(infile,"-") )
- X if (freopen (infile, "r", stdin) == NULL)
- X FatalError ("Cannot open input stream/file:", infile);
- X if (outfile && strcmp(outfile,"-") )
- X if (freopen (outfile, "w", stdout) == NULL)
- X FatalError ("Cannot open output stream/file:", outfile);
- X if (cppflags && cpp(margc,margv))
- X FatalError ("Cannot open preprocessor", CPP);
- X
- X printf ("###################################################\n");
- X printf ("## ##\n");
- X printf ("## WARNING: THIS FILE IS THE OUTPUT OF THE ##\n");
- X printf ("## `EASE' PRECOMPILER FOR SENDMAIL ##\n");
- X printf ("## CONFIGURATION FILES. ##\n");
- X printf ("## ##\n");
- X printf ("## MAKE MODIFICATIONS TO THE SOURCE ##\n");
- X printf ("## FILE ONLY. CHANGES MADE DIRECTLY ##\n");
- X printf ("## TO THIS FILE WILL DISAPPEAR THE ##\n");
- X printf ("## NEXT TIME THAT EASE IS RUN. ##\n");
- X printf ("## ##\n");
- X printf ("## $Revision: 3.2 $ ##\n");
- X printf ("## ##\n");
- X printf ("###################################################\n");
- X}
- X
- X/* cpp preprocessor code
- X * copied from Schreiner and Friedman's book:
- X * Introduction to Compiler Construction with Unix
- X *
- X * Bruce Barnett
- X */
- X
- int cpp(argc,argv)
- X int argc;
- X char **argv;
- X{
- X char **argp, *cmd;
- X extern FILE *yyin; /* for lex input */
- X extern FILE *popen();
- X int i;
- X
- X for (i = 0, argp = argv; *++argp; )
- X if (**argp == '-' &&
- X index(CPPARGS, (*argp)[1]))
- X i+=strlen(*argp) + 1;
- X if ( ! (cmd = (char *) calloc(i + sizeof CPP, sizeof(char))))
- X return -1; /* no room */
- X (void ) strcpy(cmd,CPP);
- X for (argp = argv; *++argp; )
- X if (**argp == '-' &&
- X index(CPPARGS, (*argp)[1]))
- X strcat(cmd, " "), strcat(cmd, *argp);
- X if (yyin = popen(cmd,"r"))
- X i = 0; /* all's well */
- X else
- X i = -1; /* no preprocessor */
- X cfree(cmd);
- X return i;
- X}
- END_OF_FILE
- if test 7952 -ne `wc -c <'src/main.c'`; then
- echo shar: \"'src/main.c'\" unpacked with wrong size!
- fi
- # end of 'src/main.c'
- fi
- if test -f 'src/strops.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/strops.c'\"
- else
- echo shar: Extracting \"'src/strops.c'\" \(17077 characters\)
- sed "s/^X//" >'src/strops.c' <<'END_OF_FILE'
- X#ifdef FLUKE
- X# ifndef LINT
- X static char RCSid[] = "@(#)FLUKE $Header: /home/kreskin/u0/barnett/Src/Ease/ease/src/RCS/strops.c,v 3.4 1991/10/15 17:02:04 barnett Exp $";
- X# endif LINT
- X#endif FLUKE
- X
- X/*
- X * strops.c -- Contains string operation routines used for constructing
- X * definitions in cf format.
- X *
- X * author -- James S. Schoner, Purdue University Computing Center,
- X * West Lafayette, Indiana 47907
- X *
- X * date -- July 9, 1985
- X *
- X * Copyright (c) 1985 by Purdue Research Foundation
- X *
- X * All rights reserved.
- X *
- X * $Log: strops.c,v $
- X * Revision 3.4 1991/10/15 17:02:04 barnett
- X * Detect if (one_or_more) next ($2) error
- X *
- X * Revision 3.3 1991/09/09 16:33:23 barnett
- X * Minor bug fix release
- X *
- X * Revision 3.2 1991/05/16 10:45:25 barnett
- X * Better support for System V machines
- X * Support for machines with read only text segments
- X *
- X * Revision 3.1 1991/02/25 22:09:52 barnett
- X * Fixed some portability problems
- X *
- X * Revision 3.0 1991/02/22 18:50:27 barnett
- X * Added support for HP/UX and IDA sendmail.
- X *
- X * Revision 2.1 1990/01/30 15:52:55 jeff
- X * Added SunOS/Ultrix/IDA extensions Jan 24, 1989 Bruce Barnett
- X *
- X * Revision 2.0 88/06/15 14:42:55 root
- X * Baseline release for net posting. ADR.
- X */
- X
- X#include "fixstrings.h"
- X#include <stdio.h>
- X#include <strings.h>
- X#include <ctype.h>
- X#include "symtab.h"
- X
- X#define MAXTOKPOS 99 /* maximum number of token positions */
- X#define MAXNAME 1024 /* maximum length of an identifier */
- X
- extern struct he *LookupSymbol ();
- extern char MakeMac ();
- extern void FatalError (),
- X PrintError (),
- X ErrorReport ();
- extern char * malloc ();
- X
- short Rformat = FALSE; /* class read format flag */
- short number_of_fields = 0; /* number of fields on this line */
- X#ifdef DATA_RW
- static char *Ptok = "$ "; /* positional token structure */
- static char *Cfield = "$= "; /* class reference structure */
- X#else
- static char *Ptok = NULL; /* positional token structure */
- static char *Cfield = NULL; /* class reference structure */
- X#endif
- static char *Ofield = "$-"; /* one token match structure */
- static char *Zfield = "$*"; /* zero or more tokens structure */
- static char *Pfield = "$+"; /* one or more tokens structure */
- X
- X/*
- X * FLUKE jps 25-apr-86
- X *
- X * Add the three new $%x, $%y, and $!x match operators that Sun introduced
- X * with release 3.0.
- X */
- X
- X#ifdef DATA_RW
- static char *Mfield = "$% "; /* match in specified YP map */
- static char *Nfield = "$! "; /* no match in specified YP map */
- static char *Mtest = "$? "; /* conditional macro test string */
- X#else
- static char *Mfield = NULL; /* match in specified YP map */
- static char *Nfield = NULL; /* no match in specified YP map */
- static char *Mtest = NULL; /* conditional macro test string */
- X#endif
- X
- X#ifndef DATA_RW
- X/* This section of code is for those machines with split text and data
- X * areas - where string constants are not modifiable
- X */
- X#define nil (char *)0
- X
- char * Strdup(string) /* a clone of the strdup() routine */
- char *string;
- X{
- X char *s;
- X s=malloc(strlen(string));
- X if (!s) return (nil);
- X (void) sprintf(s,"%s",string);
- X return (s);
- X}
- void InitStrOps()
- X{
- X if(!(Ptok = Strdup("$ ")) || !(Cfield = Strdup("$= ")) ||
- X !(Mfield = Strdup("$% ")) || !(Nfield = Strdup("$! ")) ||
- X !(Mtest = Strdup("$? ")))
- X FatalError("Out of memory in InitStrOps()", (char *)NULL);
- X}
- X#endif
- X
- X
- X/*
- X * ConvOpt () -- Convert an Ease option identifier (optid) by returning a
- X * string representation of the cf format.
- X *
- X */
- char *
- ConvOpt (optid)
- register enum opts optid;
- X{
- X switch (optid) {
- X case opt_A : return ("A");
- X case opt_a : return ("a");
- X case opt_B : return ("B");
- X case opt_b : return ("b");
- X case d_opt_b: return ("b");
- X case opt_C : return ("C");
- X case opt_c : return ("c");
- X case opt_D : return ("D");
- X case opt_d : return ("d");
- X case opt_e :
- X case e_opt_e: return ("e");
- X case opt_F : return ("F");
- X case opt_f : return ("f");
- X case opt_g : return ("g");
- X case opt_h : return ("h"); /* SunOS Maxhops */
- X case opt_H : return ("H");
- X case opt_I : return ("I"); /* HP/UX */
- X case opt_i :
- X case d_opt_i: return ("i");
- X case opt_L : return ("L");
- X case opt_m :
- X case e_opt_m: return ("m");
- X case opt_N : return ("N");
- X case opt_n : return ("n");
- X case opt_o : return ("o");
- X case opt_P : return ("P");
- X case e_opt_p: return ("p");
- X case opt_Q : return ("Q");
- X case opt_q : return ("q");
- X case d_opt_q: return ("q");
- X case opt_r : return ("r");
- X case opt_R : return ("R");
- X case opt_S : return ("S");
- X case opt_s : return ("s");
- X case opt_T : return ("T");
- X case opt_t : return ("t");
- X case opt_u : return ("u");
- X case opt_v : return ("v");
- X case opt_W : return ("W");
- X case e_opt_w: return ("w");
- X case opt_x : return ("x");
- X case opt_X : return ("X");
- X case opt_y : return ("y");
- X case opt_Y : return ("Y");
- X case opt_z : return ("z");
- X case opt_Z : return ("Z");
- X case e_opt_z: return ("z");
- X case opt_SL : return ("/");
- X default : FatalError ("Bad case in ConvOpt ()", (char *) NULL);
- X }
- X /*NOTREACHED*/
- X}
- X
- X
- X/*
- X * ConvFlg () -- Convert an Ease mailer flag identifier (flgid) by
- X * string representation of the cf format.
- X *
- X */
- char *
- ConvFlg (flgid)
- register enum flgs flgid; /* flag identifier */
- X{
- X switch (flgid) {
- X case flg_f: return ("f");
- X case flg_r: return ("r");
- X case flg_S: return ("S");
- X case flg_n: return ("n");
- X case flg_l: return ("l");
- X case flg_s: return ("s");
- X case flg_m: return ("m");
- X case flg_F: return ("F");
- X case flg_D: return ("D");
- X case flg_M: return ("M");
- X case flg_x: return ("x");
- X case flg_P: return ("P");
- X case flg_u: return ("u");
- X case flg_h: return ("h");
- X case flg_H: return ("H");
- X case flg_A: return ("A");
- X case flg_U: return ("U");
- X case flg_e: return ("e");
- X case flg_X: return ("X");
- X case flg_L: return ("L");
- X case flg_p: return ("p");
- X case flg_I: return ("I");
- X case flg_C: return ("C");
- X case flg_E: return ("E");
- X case flg_R: return ("R");
- X case flg_V: return ("V"); /* IDA */
- X case flg_B: return ("B"); /* IDA */
- X default : FatalError ("Bad case in ConvFlg ()", (char *) NULL);
- X }
- X /*NOTREACHED*/
- X}
- X
- X
- X/*
- X * ConvMat () -- Convert an Ease mailer attribute (mat) by returning a
- X * string representation of the cf format.
- X *
- X */
- char *
- ConvMat (mat)
- register enum mats mat; /* mailer attribute flag */
- X{
- X switch (mat) {
- X case mat_path : return ("P");
- X case mat_flags : return ("F");
- X case mat_sender : return ("S");
- X case mat_recipient : return ("R");
- X case mat_argv : return ("A");
- X case mat_eol : return ("E");
- X case mat_maxsize : return ("M");
- X default : FatalError ("Bad case in ConvMat ()", (char *) NULL);
- X }
- X /*NOTREACHED*/
- X}
- X
- X
- X/*
- X * MacScan () -- Scan a string (pstring) for macros, replacing the Ease
- X * form with the one-character form required by cf format.
- X *
- X */
- char *
- MacScan (pstring)
- char *pstring; /* macro expandable string */
- X{
- X register char *searchptr; /* string search pointer */
- X register char *bptr, *eptr; /* macro begin and end pointers */
- X char macname [MAXNAME]; /* macro name buffer */
- X int quote = 0; /* flag for detecting a quote() function */
- X
- X if ((searchptr = pstring) == NULL)
- X return ((char *) NULL);
- X while (*searchptr != '\0') /* find and rewrite all macros */
- X if (*searchptr == '\\') {
- X searchptr = searchptr + 2;
- X continue;
- X } else if (*searchptr++ == '$') {
- X if (*searchptr == '{') {
- X if (sscanf (searchptr + 1, "quote(%[^)])", macname) == 1) {
- X /* a quote(macro) sequence */
- X quote++;
- X } else if (sscanf (searchptr + 1, "%[^}]", macname) != 1) {
- X PrintError ("Invalid macro format: %s", searchptr + 1);
- X return ((char *) NULL);
- X }
- X if (quote) {
- X quote=0;
- X *searchptr++='!'; /* insert a quote */
- X /* insert the macro letter */
- X *searchptr++ = MakeMac (LookupSymbol (macname),
- X (unsigned) ID_MACRO);
- X /* now looking at quote( */
- X /* must skip over everything until )}, and then rewrite
- X the rest of the macro */
- X bptr = eptr = searchptr;
- X while (*eptr && *eptr != ')') /* skip to quote */
- X eptr++;
- X while (*eptr && *eptr != '}') /* skip past } */
- X eptr++;
- X eptr++;
- X do /* copy everything from eptr to end of line */
- X *bptr++ = *eptr;
- X while (*eptr++ != '\0');
- X } else {
- X *searchptr++ = MakeMac (LookupSymbol (macname),
- X (unsigned) ID_MACRO);
- X bptr = eptr = searchptr;
- X while (*eptr++ != '}') /* delete until end of {name} */
- X /* empty */ ;
- X do /* copy rest of line */
- X *bptr++ = *eptr;
- X while (*eptr++ != '\0');
- X }
- X } else if (isupper(*searchptr)){ /* $ not followed by { */
- X /* macro name might be one character */
- X /* but or might be more than one. */
- X if (sscanf (searchptr, "%[A-Z]", macname) != 1) {
- X PrintError ("Invalid macro format: %s", searchptr + 1);
- X return ((char *) NULL);
- X }
- X *searchptr++ = MakeMac (LookupSymbol (macname),
- X (unsigned) ID_MACRO);
- X bptr = eptr = searchptr;
- X while (isupper(*eptr)) /* delete old macro chars */
- X eptr++;
- X do
- X *bptr++ = *eptr;
- X while (*eptr++ != '\0');
- X }
- X } /* end of (if char == '$' ) */
- X return (pstring);
- X}
- X
- X
- X/*
- X * MakeRStr () -- Construct and return a pointer to a class read string
- X * using the filename fname and read format rformat.
- X *
- X */
- char *
- MakeRStr (fname, rformat)
- char *fname, /* file name for class read */
- X *rformat; /* format for class read */
- X{
- X register char *res; /* resultant read string */
- X
- X Rformat = TRUE; /* set read format flag */
- X if (rformat == NULL)
- X return (fname);
- X res = (char *) realloc (fname, strlen (fname) + strlen (rformat) + 2);
- X if (res == NULL)
- X FatalError ("System out of string space in MakeRStr ()", (char *) NULL);
- X res = strcat (res, " "); /* construct read string */
- X res = strcat (res, rformat);
- X free (rformat);
- X return (res);
- X}
- X
- X
- X/*
- X * ListAppend () -- Append string list2 to string list1 using the
- X * separator sep. A pointer to the newly constructed
- X * string is returned.
- X *
- X */
- char *
- ListAppend (list1, list2, sep)
- char *list1, /* first string */
- X *list2, /* second string */
- X *sep; /* string separator */
- X{
- X register char *res; /* resultant string */
- X
- X res = (char *) malloc (strlen (list1) + strlen (list2) + strlen (sep) + 1);
- X if (res == NULL)
- X FatalError ("System out of string space in ListAppend ()", (char *) NULL);
- X res = strcpy (res, list1);
- X if (list1 != NULL) /* use separator if first string not null */
- X res = strcat (res, sep);
- X res = strcat (res, list2);
- X return (res);
- X}
- X
- X
- X/*
- X * MakeCond () -- Construct a macro conditional string in cf format. The
- X * conditional is based on the macro testmac, with an "if
- X * set" result ifstring, which may contain an optional
- X * "if not set" result string appended to it.
- X *
- X */
- char *
- MakeCond (testmac, ifstring)
- struct he *testmac; /* macro for conditional testing */
- char *ifstring; /* "if macro set" result string(s) */
- X{
- X register char *res; /* resultant conditional string */
- X
- X Mtest[2] = MakeMac (testmac, (unsigned) ID_MACRO); /* get one-char macro rep */
- X res = (char *) malloc (strlen (ifstring) + 6);
- X if (res == NULL)
- X FatalError ("System out of string space in MakeCond ()", (char *) NULL);
- X res = strcpy (res, Mtest);
- X res = strcat (res, ifstring); /* build result part */
- X res = strcat (res, "$."); /* end of conditional */
- X free (ifstring);
- X return (res);
- X}
- X
- X
- X/*
- X * MakePosTok () -- Construct and return a positional token string
- X * representation from the parameter num.
- X *
- X */
- char *
- MakePosTok (num)
- register int num; /* numerical value of positional token */
- X{
- X char buf[100];
- X if (num > MAXTOKPOS) {
- X ErrorReport ("Positional token too large.\n");
- X return ((char *) NULL);
- X } else {
- X if (num > number_of_fields) {
- X sprintf(buf," $%d used in right hand side of rule, but maximum positional parameter is %d\n", num, number_of_fields);
- X ErrorReport(buf);
- X }
- X if (num > 9) { /* two-digit positional token */
- X Ptok[1] = '0' + (num / 10);
- X Ptok[2] = '0' + (num % 10);
- X Ptok[3] = '\0';
- X } else {
- X Ptok[1] = '0' + num;
- X Ptok[2] = '\0';
- X }
- X return (Ptok);
- X }
- X}
- X
- X
- X/*
- X * Bracket () -- Construct and return a cf string form of the
- X * canonicalization of the string identifier passed in
- X * the string parameter psb if dflag is true, else
- X * simply bracket the identifier without dollar signs
- X * for numeric hostname specifications.
- X *
- X */
- char *
- Bracket (psb, dflag)
- char *psb; /* identifier to be canonicalized */
- short dflag; /* dollar flag */
- X{
- X register char *res; /* resultant cf form */
- X register short extra; /* extra space needed for malloc */
- X
- X extra = dflag ? 5 : 3;
- X res = (char *) malloc (strlen (psb) + extra);
- X if (res == NULL)
- X FatalError ("System out of string space in Bracket ()", (char *) NULL);
- X if (dflag)
- X res = strcpy (res, "$[");
- X else
- X res = strcpy (res, "[");
- X res = strcat (res, psb);
- X if (dflag)
- X res = strcat (res, "$");
- X res = strcat (res, "]");
- X return (res);
- X}
- X/*
- X * DbmParen () -- Construct and return a cf string form of the
- X * dbm reference of the IDA database identifier passed in
- X * the string parameter db_psb, looking up the string identifier
- X * passed in the string parameter lup_psb.
- X *
- X */
- char *
- DbmParen (db_psb, lup_psb)
- char *db_psb; /* identifier of data base */
- char *lup_psb; /* identifier being looked up */
- X{
- X register char *res; /* resultant cf form */
- X
- X res = (char *) malloc (strlen (lup_psb) + 7);
- X if (res == NULL)
- X FatalError ("System out of string space in DbmParen ()", (char *) NULL);
- X res = strcpy (res, "$(x ");
- X *(res+2) = *db_psb;
- X res = strcat (res, lup_psb);
- X res = strcat (res, " $)");
- X return (res);
- X}
- X
- X
- X/*
- X * MakeRSCall () -- Construct and return a cf string form of a call
- X * to a ruleset (cid), which would pass to it the
- X * remainder of a rewriting address (rwaddr).
- X *
- X */
- char *
- MakeRSCall (cid, rwaddr)
- register struct he *cid; /* called ruleset identifier */
- register char *rwaddr; /* remainder of rewriting address */
- X{
- X register char *res; /* resultant cf string for the call */
- X
- X if (!ISRULESET(cid->idtype)) { /* check validity of ruleset */
- X PrintError ("Undefined ruleset identifier: %s", cid->psb);
- X return ((char *) NULL);
- X }
- X /*
- X * FLUKE jps - 8-may-86 - boost string size by 1 to accomodate space
- X * character.
- X */
- X res = (char *) malloc (strlen (cid->idval.rsn) + strlen (rwaddr) + 4);
- X if (res == NULL)
- X FatalError ("System out of string space in MakeRSCall ()", (char *) NULL);
- X res = strcpy (res, "$>"); /* construct the call string */
- X res = strcat (res, cid->idval.rsn);
- X res = strcat (res, " "); /* FLUKE jps - work around sendmail bug:
- X * whitespace is needed to separate tokens:
- X * for example: $>30$D will confuse
- X * sendmail, but $>30 $D is OK.
- X */
- X res = strcat (res, rwaddr);
- X return (res);
- X}
- X
- X
- X/*
- X * MakeField () -- Construct and return the cf string format for a
- X * field variable. The match count (count), an optional
- X * class (class), and a match repetition flag (fstar)
- X * are used to determine what type of field string to
- X * construct.
- X *
- X * FLUKE jps 25-apr-86 - Modified to add a fourth parameter "isYPmap". This
- X * supports Sun's new Yellow Pages match patterns added in release 3.0.
- X *
- X */
- char *
- X MakeField (count, class, fstar, isYPmap)
- register int count; /* match count (0 or 1) */
- register struct he *class; /* optional class type */
- register short fstar; /* repetition flag */
- register short isYPmap; /* "class" name is really a YP map name */
- X{
- X switch (count) {
- X case 0: if (class == NULL) /* any token is valid */
- X if (fstar)
- X return (Zfield);
- X else {
- X ErrorReport ("Invalid field type.\n");
- X return ((char *) NULL);
- X }
- X else { /* match 0 from class or map */
- X if (isYPmap) {
- X /* "class" is a misnomer here; it's really
- X * a simple macro name for a YP map.
- X * FLUKE jps 25-apr-86
- X */
- X Nfield[2] = MakeMac (class, (unsigned) ID_MACRO);
- X return (Nfield);
- X } else {
- X Cfield[1] = '~';
- X Cfield[2] = MakeMac (class, (unsigned) ID_CLASS);
- X return (Cfield);
- X }
- X }
- X case 1: if (class == NULL) /* any token is valid */
- X if (fstar)
- X return (Pfield);
- X else
- X return (Ofield);
- X else { /* match 1 from class or map */
- X if (isYPmap) {
- X /* "class" is a misnomer here; it's really
- X * a simple macro name for a YP map.
- X * FLUKE jps 25-apr-86
- X */
- X Mfield[2] = MakeMac (class, (unsigned) ID_MACRO);
- X return (Mfield);
- X } else {
- X Cfield[1] = '=';
- X Cfield[2] = MakeMac (class, (unsigned) ID_CLASS);
- X return (Cfield);
- X }
- X }
- X default: ErrorReport ("Invalid field type.\n");
- X }
- X /*NOTREACHED*/
- X}
- END_OF_FILE
- if test 17077 -ne `wc -c <'src/strops.c'`; then
- echo shar: \"'src/strops.c'\" unpacked with wrong size!
- fi
- # end of 'src/strops.c'
- fi
- echo shar: End of archive 3 \(of 6\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 6 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 6 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-